Skip to content

fix: add type definitions, extract hook, and implement security harde…#705

Open
HardikTi13 wants to merge 10 commits intoaccordproject:mainfrom
HardikTi13:fix/build-security-type-issues
Open

fix: add type definitions, extract hook, and implement security harde…#705
HardikTi13 wants to merge 10 commits intoaccordproject:mainfrom
HardikTi13:fix/build-security-type-issues

Conversation

@HardikTi13
Copy link

Closes #703

Summary

This PR fixes multiple critical issues affecting build stability, type safety, and application security. It also includes refactoring improvements to enhance modularity and remove lint warnings.


Changes

Build & Type Safety

  • Added src/types/markdown-template.d.ts to provide proper types for @accordproject/markdown-template, resolving TemplateMarkTransformer errors.
  • Fixed store.ts
    • Removed unnecessary eslint-disable comments.
    • Removed unsafe type assertions (as object, as unknown).
    • Corrected type casting to Record<string, unknown> for TemplateMarkInterpreter.generate.
  • Removed unused imports (e.g., monaco in CodeSelectionMenu.tsx) that were causing build failures.

Refactoring

  • Extracted useCodeSelection hook
    src/components/CodeSelectionMenu.tsxsrc/hooks/useCodeSelection.tsx
  • Resolves React Refresh lint warning (file should only export components).
  • Improves modularity and avoids potential circular dependencies.
  • Updated:
    • MarkdownEditor
    • ConcertoEditor
    • JSONEditor
      to use the new hook location.

Security Hardening

  • Added DOMPurify sanitization before rendering HTML with dangerouslySetInnerHTML.
    • src/pages/MainContainer.tsx
    • src/AgreementHtml.tsx
  • Added rel="noopener noreferrer" to external links in src/components/Footer.tsx to prevent reverse tabnabbing.

Result

  • Build passes successfully
  • Improved type safety
  • Removed lint warnings
  • XSS-safe HTML rendering
  • Prevented reverse tabnabbing
  • Cleaner and more maintainable codebase

…ning

Signed-off-by: Hardik Tiwari <tiwarihardik131105@gmail.com>
@HardikTi13 HardikTi13 requested a review from a team as a code owner February 14, 2026 19:06
@netlify
Copy link

netlify bot commented Feb 14, 2026

Deploy Preview for ap-template-playground ready!

Name Link
🔨 Latest commit 4b4cd1c
🔍 Latest deploy log https://app.netlify.com/projects/ap-template-playground/deploys/69ac70e799448b000889cbaf
😎 Deploy Preview https://deploy-preview-705--ap-template-playground.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@mttrbrts mttrbrts requested a review from Copilot February 25, 2026 20:20
Copy link
Member

@mttrbrts mttrbrts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review build conflicts

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses build stability, type safety, and security concerns in the Template Playground application. The changes include adding type definitions for an external library, implementing XSS protection through HTML sanitization, preventing reverse tabnabbing attacks on external links, refactoring a React hook for better modularity, and adding DOMPurify as a dependency.

Changes:

  • Added type definitions for @accordproject/markdown-template to resolve TypeScript errors
  • Implemented DOMPurify sanitization for HTML rendering to prevent XSS attacks
  • Added rel="noopener noreferrer" to external links in Footer component to prevent reverse tabnabbing
  • Extracted useCodeSelection hook from CodeSelectionMenu component to a separate hooks file
  • Added dompurify and @types/dompurify dependencies

Reviewed changes

Copilot reviewed 9 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/types/markdown-template.d.ts Adds TypeScript type definitions for TemplateMarkTransformer class (though the signature doesn't match actual usage)
src/pages/MainContainer.tsx Adds DOMPurify sanitization before rendering agreementHtml with dangerouslySetInnerHTML
src/hooks/useCodeSelection.tsx Extracts code selection logic into a reusable hook (creates architectural coupling by returning JSX component)
src/editors/MarkdownEditor.tsx Updates import path for useCodeSelection hook
src/editors/JSONEditor.tsx Updates import path for useCodeSelection hook
src/editors/ConcertoEditor.tsx Updates import path for useCodeSelection hook
src/components/Footer.tsx Adds rel="noopener noreferrer" to all external links for security
src/components/CodeSelectionMenu.tsx Removes useCodeSelection hook and monaco import (moved to separate hook file)
src/AgreementHtml.tsx Adds DOMPurify sanitization before rendering agreementHtml with dangerouslySetInnerHTML
package.json Adds dompurify and @types/dompurify dependencies
package-lock.json Updates lock file with new dependencies and corrects @types/trusted-types optional flag
lint.txt Build/test output file that should not be committed
lint-errors.txt Build/test output file that should not be committed

Comment on lines +4 to +62
import CodeSelectionMenu from '../components/CodeSelectionMenu';

export const useCodeSelection = (editorType: 'markdown' | 'concerto' | 'json') => {
const [selectedText, setSelectedText] = useState('');
const [menuPosition, setMenuPosition] = useState<{ x: number; y: number } | null>(null);
const [showMenu, setShowMenu] = useState(false);
const enableCodeSelectionMenu = useAppStore((state) => state.aiConfig?.enableCodeSelectionMenu ?? true);


const handleSelection = (editor: monaco.editor.IStandaloneCodeEditor) => {
const selection = editor.getSelection();
if (selection && !selection.isEmpty()) {
const selectedText = editor.getModel()?.getValueInRange(selection).trim();
if (selectedText && selectedText.length > 0) {
const position = editor.getScrolledVisiblePosition(selection.getStartPosition());
const editorContainer = editor.getDomNode()?.closest('.editorwrapper');
const editorRect = editorContainer?.getBoundingClientRect();

let x: number, y: number;

if (editorRect && position) {
x = Math.max(editorRect.left + 20, Math.min(position.left, editorRect.right - 150));
y = Math.max(editorRect.top + 20, Math.min(position.top, editorRect.bottom - 50));

x = Math.max(10, Math.min(x, window.innerWidth - 150));
y = Math.max(10, Math.min(y, window.innerHeight - 50));
} else if (position) {
x = Math.max(10, Math.min(position.left, window.innerWidth - 150));
y = Math.max(10, Math.min(position.top, window.innerHeight - 50));
} else {
return;
}

setSelectedText(selectedText);
setMenuPosition({
x: x,
y: y
});
setShowMenu(true);
}
} else {
setShowMenu(false);
}
}

const closeMenu = () => {
setShowMenu(false);
setSelectedText('');
setMenuPosition(null);
};

const MenuComponent = (enableCodeSelectionMenu && showMenu && selectedText && menuPosition) ? (
<CodeSelectionMenu
selectedText={selectedText}
position={menuPosition}
onClose={closeMenu}
editorType={editorType}
/>
) : null;
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new hook file imports CodeSelectionMenu component at line 4, creating a circular dependency. The hook is meant to be used by editors that need the code selection functionality, but it imports the component that should use the hook's return value. This defeats the purpose of extracting the hook for modularity. The MenuComponent should be rendered by the consuming component (MarkdownEditor, JSONEditor, ConcertoEditor) instead of being created inside the hook. The hook should only return the state and handlers, not the JSX component.

Copilot uses AI. Check for mistakes.
Resolved conflicts in package-lock.json and src/AgreementHtml.tsx

Signed-off-by: HardikTi13 <tiwari.hardik1399@gmail.com>
@HardikTi13 HardikTi13 force-pushed the fix/build-security-type-issues branch from d5f017f to b2da04a Compare February 25, 2026 20:45
- Hook now only exports state and handlers (no JSX)

- Editors import and render CodeSelectionMenu directly

- Renamed useCodeSelection.tsx to useCodeSelection.ts (no JSX needed)

Signed-off-by: HardikTi13 <tiwari.hardik1399@gmail.com>
I, Hardik Tiwari <tiwarihardik131105@gmail.com>, hereby add my Signed-off-by to this commit: 418bf33

Signed-off-by: Hardik Tiwari <tiwarihardik131105@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 11 changed files in this pull request and generated 1 comment.

Copy link
Member

@mttrbrts mttrbrts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the lint txt files and the change to package.json.

Also, I recommend removing the typedefs for now, I've left a comment about how to do that properly which can be done in a separate PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move typescript typedef upstream to the @accordproject/markdown-template package.
There is an example in the concerto repository for creating typedefs from jsdocs.
accordproject/markdown-transform#648

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Critical fixes for build, type safety, and XSS protection

3 participants